package org.dromara.system.controller.system;

import cn.dev33.satoken.annotation.SaCheckPermission;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.idempotent.annotation.RepeatSubmit;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.dromara.system.domain.bo.SysClientBo;
import org.dromara.system.domain.vo.SysClientVo;
import org.dromara.system.service.ISysClientService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：客户端管理
 */
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/system/client")
public class SysClientController extends BaseController {

    /**
     * 客户端管理Service接口
     */
    private final ISysClientService sysClientService;

    /**
     * 查询客户端管理列表
     *
     * @param bo SysClientBo对象，用于传递查询条件
     * @param pageQuery 分页查询对象，用于指定分页参数
     * @return 返回TableDataInfo对象，包含了客户端列表和分页信息
     */
    @SaCheckPermission("system:client:list")
    @GetMapping("/list")
    public TableDataInfo<SysClientVo> list(SysClientBo bo, PageQuery pageQuery) {
        return sysClientService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出客户端管理列表
     *
     * @param bo 客户端业务对象，用于查询条件
     * @param response HTTP响应对象，用于导出文件流
     */
    @SaCheckPermission("system:client:export")
    @Log(title = "客户端管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(SysClientBo bo, HttpServletResponse response) {
        // 查询客户端信息列表
        List<SysClientVo> list = sysClientService.queryList(bo);
        // 导出客户端信息列表到Excel文件，并发送到前端响应
        ExcelUtil.exportExcel(list, "客户端管理", SysClientVo.class, response);
    }

    /**
     * 获取客户端管理详细信息
     * 说明：
     * - 本方法使用了@NotNull注解来确保在调用时主键ID不为空，避免无效的查询操作
     * - 通过调用sysClientService的queryById方法实现数据库查询，体现了服务间的协作
     * - 利用R.ok封装查询结果，确保返回值符合统一的响应格式
     *
     * @param id 主键，不能为空，用于标识特定的系统客户端
     * @return 返回封装好的系统客户端信息对象，如果查询成功，则状态为ok
     */
    @SaCheckPermission("system:client:query")
    @GetMapping("/{id}")
    public R<SysClientVo> getInfo(@NotNull(message = "主键不能为空")
                                  @PathVariable Long id) {
        return R.ok(sysClientService.queryById(id));
    }

    /**
     * 新增客户端管理
     * 该方法的作用是通过接收一个SysClientBo对象，将其转换为系统客户端信息并插入数据库中
     * 使用了@Validated注解来确保对象符合添加操作的验证要求，保证了数据的合法性
     * 通过@RequestBody注解表明参数是从请求体中获取的，适合于POST等HTTP请求
     * 最终返回的是一个R<Void>对象，其中Void表示不返回具体的数据内容，只有操作结果的状态
     *
     * @param bo 系统客户端信息对象，携带了所有必要的属性值
     * @return 返回一个R对象，其中不携带数据（Void类型），用于表示操作结果
     */
    @SaCheckPermission("system:client:add")
    @Log(title = "客户端管理", businessType = BusinessType.INSERT)
    @RepeatSubmit()
    @PostMapping()
    public R<Void> add(@Validated(AddGroup.class) @RequestBody SysClientBo bo) {
        return toAjax(sysClientService.insertByBo(bo));
    }

    /**
     * 修改客户端管理
     * 本方法使用@Validated注解配合自定义的校验分组EditGroup进行参数合法性校验，确保更新操作的数据安全
     * 通过@RequestBody注解接收SysClientBo类型的请求体数据，调用sysClientService.updateByBo(bo)方法完成更新操作
     * 返回R<Void>类型的响应结果，其中Void表示无返回数据，适用于更新、删除等操作
     *
     * @param bo 封装了客户端信息的请求体，必须符合EditGroup校验规则
     * @return R<Void>类型的响应结果，包含更新操作的状态信息
     */
    @SaCheckPermission("system:client:edit")
    @Log(title = "客户端管理", businessType = BusinessType.UPDATE)
    @RepeatSubmit()
    @PutMapping()
    public R<Void> edit(@Validated(EditGroup.class) @RequestBody SysClientBo bo) {
        return toAjax(sysClientService.updateByBo(bo));
    }

    /**
     * 状态修改
     * 更新客户端状态
     * 通过此方法，能够更新指定客户端的状态，实现客户端的启用或禁用
     *
     * @param bo 请求体，包含客户端ID和新的状态信息
     * @return 返回一个R对象，包含操作结果信息
     */
    @SaCheckPermission("system:client:edit")
    @Log(title = "客户端管理", businessType = BusinessType.UPDATE)
    @PutMapping("/changeStatus")
    public R<Void> changeStatus(@RequestBody SysClientBo bo) {
        return toAjax(sysClientService.updateUserStatus(bo.getClientId(), bo.getStatus()));
    }

    /**
     * 删除客户端管理
     * 该方法用于根据提供的主键数组批量删除客户端信息它通过调用`sysClientService.deleteWithValidByIds`方法来实现，
     * 该方法需要一个包含主键ID的列表以及一个标志，指示是否在删除前进行有效性验证
     * 主键数组通过URL路径变量`ids`传入，且必须至少包含一个有效的ID，否则抛出NotEmpty约束验证异常
     *
     * @param ids 主键串，通过URL路径变量传入，不能为空
     * @return R<Void> 返回一个通用结果对象，表示操作结果，不携带数据负载
     */
    @SaCheckPermission("system:client:remove")
    @Log(title = "客户端管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Void> remove(@NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] ids) {
        return toAjax(sysClientService.deleteWithValidByIds(List.of(ids), true));
    }
}
